
const { promises } = require('dns')
const fs = require('fs')
const { checkDir, clearDir, setFileName } = require('../../utils/files')
const singelLog = require('single-line-log')
const request = require('request')
const path = require('path')
const { calcTimeInterval } = require('../../utils/time')
class TSDownloader {
    constructor() {
        this.filename = ''  // 下载文件名称
        this.failList = [] // 下载失败文件
        this.source = {} // 下载资源
        this.downloadPath = '', // 下载文件路径
            this.dirReady = true // 处理下载文件夹
        this.start = null // 开始下载时间
        this.sourceUrlList = []
        this.subSource = [] // 分段下载资源
        this.subIndex = 0 //分段下载指针
        this.increment = 5  //分段下载长度
        this.downloadDelay = 1 // 每个请求间延时
        this.checkDelay = 5000 // 检查下载状态延时
        this.done = this.subIndex // 下载成功数

    }

    setSource(source) {
        if (!source) {
            console.trace('无效资源')
            return
        }
        this.source = source
        return this
    }

    getSource() {
        return this.source.nameList
    }



    //下载
    async download(filename, downloadPath) {

        await this.beforeDownload(downloadPath).then(
            ({ success }) => {
                if (success) this.dirReady = true
            }
        )

        // 获取下载链接
        this.sourceUrlList = this.anasysSource(filename)
        this.start = new Date()

        // this.startDownload(this.sourceUrlList)
        this.subDownload().then(res=>{
            console.log(res)
        })

    }

    subDownload(){
        return new Promise(resolve=>{
            this.subSource = this.sourceUrlList.slice(this.subIndex, this.subIndex+this.increment)
            // console.log('debug', this.subIndex, this.increment)
            console.log(`开始下载${this.subIndex}-${this.subIndex + this.increment-1}/${this.sourceUrlList.length}`)
            this.startDownload().then(res=>{
                this.subIndex += this.increment
                console.log(this.subIndex ,this.sourceUrlList.length)
                if (this.subIndex >= this.sourceUrlList.length){
                    resolve({success:true,msg:'所有资源下载完成'})
                }else{
                    // console.log('debug',this.subSource)
                    this.subDownload()
                }
            })
            
        })
    }


    // 开始下载文件
    startDownload(source = this.subSource, failFlag) {
        return new Promise((resolve) => {
            // if (source.length == 0 && failFlag) {
            //     resolve('下载成功')
            // }
            const that = this
            let timer = null
            let index = 0
            timer = setInterval(async () => {
                const tsItem = source[index]
                const tsFilename = `${that.filename}${setFileName(tsItem.sort)}.ts`
                const tsfilePath = path.resolve(that.downloadPath, tsFilename)
                // singelLog.stdout(tsFilename, '\n')

                const stream = fs.createWriteStream(tsfilePath, (err) => {
                    console.log('创建失败')
                });
                request({ url: tsItem.url, setTimeout: 10000 }, downloadFailHandler)
                    .pipe(stream)
                    .on('close', successHandler);

                // 下载成功
                function successHandler() {
                    // 从失败列表中删除此项
                    const index = that.failList.indexOf(tsItem)
                    if (index > -1) {
                        that.failList.splice(index, 1)
                    }
                    that.done += 1
                    const time = calcTimeInterval(that.start, new Date())
                    const { hours, minutes, seconds } = time
                    singelLog.stdout(`${tsFilename}下载完成 ${that.subIndex}-${that.subIndex + that.increment - 1}/${that.sourceUrlList.length}/${that.done}/${source.length}/${that.failList.length} (分段/总数/成功/失败)  总用时${hours}:${minutes}:${seconds}`, '\n')
                }

                // 下载失败
                function downloadFailHandler(err) {
                    if (err) {
                        // 删除创建的文件
                        // fs.unlinkSync(tsfilePath)
                        const time = calcTimeInterval(that.start, new Date())
                        const { hours, minutes, seconds } = time
                        singelLog.stdout(`${tsFilename}下载失败 ${that.subIndex}-${that.subIndex + that.increment - 1}/${that.sourceUrlList.length}/${that.done}/${source.length}/${that.failList.length} (分段/总数/成功/失败)  总用时${hours}:${minutes}:${seconds}`, '\n')

                        // 记录失败文件
                        if (that.failList.indexOf(tsItem) === -1) {

                            that.failList.push(tsItem)
                        }
                    }
                }

                index += 1

                // 遍历下载完成
                if (index == source.length) {
                    clearInterval(timer)
                    timer = null
                    that.watchDownload(source).then( (res) => { 
                        if(res.success){

                            console.log('分段下载完成')
                            resolve(res)} 
                        }
                    ).catch(err=>{
                        that.startDownload(this.failList, true)
                    })

                }
            }, this.downloadDelay)
        })
    }

    // 监听单次下载动作结束
    watchDownload(source) {
        let timer = null
        return new Promise((resolve,reject) => {

            timer = setInterval(() => {
                console.log(this.done, this.failList.length, this.subIndex, this.done + this.failList.length - this.subIndex , this.subSource.length)
                if (this.done + this.failList.length -this.subIndex === this.subSource.length) {
                    clearInterval(timer)
                    timer = null
                    if (this.failList.length > 0) {
                        console.log(`${this.failList.length}个文件下载失败,开始重试`, '\n')
                        reject({success:false,msg:'下载失败'})
                    } else {
                        console.log('本次下载结束')
                        resolve({ success: true, msg: '下载完成' })
                    }
                }


            }, this.checkDelay)
        })
    }

    // 解析资源
    anasysSource(filename) {
        if (this.source.nameList.indexOf(filename) == -1) {
            console.log(`资源库中没有匹配到${filename}资源,重新选择资源${this.source.nameList}`)
            return
        }

        let res = this.source.sourceList.filter(item => item.name == filename)[0].url
        res = res.map((item, index) => {
            return {
                sort: index,
                url: item
            }
        })
        this.filename = filename
        console.log(`匹配到《${filename}》下载资源`)

        return res

    }



    async beforeDownload(downloadPath) {
        return new Promise(async (resolve, reject) => {
            // 先判断有无目标文件夹
            await checkDir(downloadPath).then(
                res => {
                    if (res.success) this.downloadPath = downloadPath
                }
            ).catch(err => {
                if (err) this.downloadPath = null
            })

            //  清空目标下载文件夹
            if (this.downloadPath) {
                clearDir(downloadPath)
                    .then(res => {
                        res.success && resolve({ success: true })
                    })
            }
        })
    }













}

module.exports = TSDownloader